Code Coverage
 
Classes and Traits
Functions and Methods
Lines
Total
0.00% covered (danger)
0.00%
0 / 1
71.43% covered (warning)
71.43%
5 / 7
CRAP
95.89% covered (success)
95.89%
70 / 73
PropertiesNormalizer
0.00% covered (danger)
0.00%
0 / 1
71.43% covered (warning)
71.43%
5 / 7
20
95.89% covered (success)
95.89%
70 / 73
 normalize
0.00% covered (danger)
0.00%
0 / 1
5.00
94.44% covered (success)
94.44%
34 / 36
 getLabel
0.00% covered (danger)
0.00%
0 / 1
4.02
88.89% covered (warning)
88.89%
8 / 9
 supportsNormalization
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 getUpdatedAt
100.00% covered (success)
100.00%
1 / 1
3
100.00% covered (success)
100.00%
9 / 9
 getAncestors
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
8 / 8
 getAncestorsIds
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
 getAncestorsCodes
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
5 / 5
<?php
namespace Akeneo\Pim\Enrichment\Component\Product\Normalizer\Indexing\Product;
use Akeneo\Pim\Enrichment\Component\Product\Model\EntityWithFamilyVariantInterface;
use Akeneo\Pim\Enrichment\Component\Product\Model\ProductInterface;
use Akeneo\Pim\Enrichment\Component\Product\Normalizer\Standard\Product\PropertiesNormalizer as StandardPropertiesNormalizer;
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
use Symfony\Component\Serializer\SerializerAwareInterface;
use Symfony\Component\Serializer\SerializerAwareTrait;
/**
 * Transform the properties of a product object (fields and product values)
 * to the indexing format.
 *
 * @author    Julien Janvier <jjanvier@akeneo.com>
 * @copyright 2017 Akeneo SAS (http://www.akeneo.com)
 * @license   http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */
class PropertiesNormalizer implements NormalizerInterface, SerializerAwareInterface
{
    use SerializerAwareTrait;
    const FIELD_COMPLETENESS = 'completeness';
    const FIELD_IN_GROUP = 'in_group';
    const FIELD_ID = 'id';
    private const FIELD_ANCESTORS = 'ancestors';
    /**
     * {@inheritdoc}
     */
    public function normalize($product, $format = null, array $context = [])
    {
        if (!$this->serializer instanceof NormalizerInterface) {
            throw new \LogicException('Serializer must be a normalizer');
        }
        $data = [];
        $data[self::FIELD_ID] = (string) $product->getId();
        $data[StandardPropertiesNormalizer::FIELD_IDENTIFIER] = $product->getIdentifier();
        $data[StandardPropertiesNormalizer::FIELD_CREATED] = $this->serializer->normalize(
            $product->getCreated(),
            $format
        );
        $data[StandardPropertiesNormalizer::FIELD_UPDATED] = $this->serializer->normalize(
            $this->getUpdatedAt($product),
            $format
        );
        $data[StandardPropertiesNormalizer::FIELD_FAMILY] = $this->serializer->normalize(
            $product->getFamily(),
            $format
        );
        $data[StandardPropertiesNormalizer::FIELD_ENABLED] = (bool) $product->isEnabled();
        $data[StandardPropertiesNormalizer::FIELD_CATEGORIES] = $product->getCategoryCodes();
        $data[StandardPropertiesNormalizer::FIELD_GROUPS] = $product->getGroupCodes();
        foreach ($product->getGroupCodes() as $groupCode) {
            $data[self::FIELD_IN_GROUP][$groupCode] = true;
        }
        $data[self::FIELD_COMPLETENESS] = !$product->getCompletenesses()->isEmpty()
            ? $this->serializer->normalize(
                $product->getCompletenesses(),
                ProductNormalizer::INDEXING_FORMAT_PRODUCT_INDEX,
                $context
            ) : [];
        $data[StandardPropertiesNormalizer::FIELD_VALUES] = !$product->getValues()->isEmpty()
            ? $this->serializer->normalize(
                $product->getValues(),
                ProductNormalizer::INDEXING_FORMAT_PRODUCT_INDEX,
                $context
            ) : [];
        $data[StandardPropertiesNormalizer::FIELD_LABEL] = $this->getLabel(
            $data[StandardPropertiesNormalizer::FIELD_VALUES],
            $product
        );
        $data[self::FIELD_ANCESTORS] = $this->getAncestors($product);
        return $data;
    }
    /**
     * Get label of the given product
     *
     * @param array            $values
     * @param ProductInterface $product
     *
     * @return array
     */
    private function getLabel(array $values, ProductInterface $product): array
    {
        if (null === $product->getFamily()) {
            return [];
        }
        $attributeAsLabel = $product->getFamily()->getAttributeAsLabel();
        if (null === $attributeAsLabel) {
            return [];
        }
        $valuePath = sprintf('%s-text', $attributeAsLabel->getCode());
        if (!isset($values[$valuePath])) {
            return [];
        }
        return $values[$valuePath];
    }
    /**
     * {@inheritdoc}
     */
    public function supportsNormalization($data, $format = null)
    {
        return $data instanceof ProductInterface && ProductNormalizer::INDEXING_FORMAT_PRODUCT_INDEX === $format;
    }
    /**
     * @param ProductInterface $product
     *
     * @return \Datetime
     */
    private function getUpdatedAt(ProductInterface $product): \Datetime
    {
        $date = $product->getUpdated();
        if ($product->isVariant()) {
            $dates = [$date];
            $parent = $product->getParent();
            while (null !== $parent) {
                $dates[] = $parent->getUpdated();
                $parent = $parent->getParent();
            }
            $date = max($dates);
        }
        return $date;
    }
    /**
     * @param ProductInterface $product
     *
     * @return array
     */
    private function getAncestors(ProductInterface $product): array
    {
        $ancestorsIds = [];
        $ancestorsCodes = [];
        if ($product->isVariant()) {
            $ancestorsIds = $this->getAncestorsIds($product);
            $ancestorsCodes = $this->getAncestorsCodes($product);
        }
        $ancestors = [
            'ids' => $ancestorsIds,
            'codes' => $ancestorsCodes,
        ];
        return $ancestors;
    }
    /**
     * @param EntityWithFamilyVariantInterface $entityWithFamilyVariant
     *
     * @return array
     */
    private function getAncestorsIds(EntityWithFamilyVariantInterface $entityWithFamilyVariant): array
    {
        $ancestorsIds = [];
        while (null !== $parent = $entityWithFamilyVariant->getParent()) {
            $ancestorsIds[] = 'product_model_' . $parent->getId();
            $entityWithFamilyVariant = $parent;
        }
        return $ancestorsIds;
    }
    /**
     * @param EntityWithFamilyVariantInterface $entityWithFamilyVariant
     *
     * @return array
     */
    private function getAncestorsCodes(EntityWithFamilyVariantInterface $entityWithFamilyVariant): array
    {
        $ancestorsCodes = [];
        while (null !== $parent = $entityWithFamilyVariant->getParent()) {
            $ancestorsCodes[] = $parent->getCode();
            $entityWithFamilyVariant = $parent;
        }
        return $ancestorsCodes;
    }
}